home *** CD-ROM | disk | FTP | other *** search
- /****************************************************************************
- *
- * COPYRIGHT 1990,91,92 BY GRACILIS INC.
- *
- * 623 Palace St.
- * Aurora, Il. 60506
- *
- * (708)-801-8800 Office
- * (708)-844-0183 (FAX - Support BBS)
- *
- * GRACILIS, INC., MAKES NO REPRESENTATIONS ABOUT THE SUITABILITY OF THIS
- * SOFTWARE FOR ANY PURPOSE.
- *
- * THIS SOFTWARE IS PROVIDED "AS IS" WITHOUT EXPRESS OR IMPLIED WARRANTY.
- *
- * Permission is granted for non-commercial use/distribution only, as long as
- * this copyright header is included intact and unaltered.
- *
- ******************************************************************************/
-
-
-
- /************************************************************************
- *
- *
- * File: ipc.c
- *
- * Rev : 1.0
- *
- * Description:
- *
- * This File contains routines that implement PackeTen Switch's
- * inter-processor driver with an interface to KA9Q's TCP/IP suite.
- *
- *
- * Routines:
- *
- * ipc_attach - Performs attach functions for TCP/IP, i.e.
- * attach the ipc driver to TCP/IP.
- *
- * ipc_raw - Applications' routine for transmitting
- * a message via ipc driver.
- *
- * ipc_recv - Applications' routine for receiving a message
- * from the ipc driver.
- *
- * ipc_stat - Applications' routine for "displaying" the
- * ipc driver statistics.
- *
- * ipc_ioctl - Set driver parameters.
- *
- * ipc_stop - Stop I/O
- *
- * ipc_init - Initialize the ipc hardware.
- *
- * ipc_txint - Handles transmit complete interrupts.
- *
- * ipc_rxint - Handles receive complete interrupts.
- *
- * ipc_entpt - Interrupt entry point
- *
- */
-
- /*
- Note: As currently implemented, if the remote side of an IPC
- link stops functioning, and we can not send our data to it,
- eventually, all of NOS buffer memory will be used up.
-
- Some strategy needs be developed to handle this problem...
- It is analagous to a link which cannot transmit due to
- a continuously appearing CARRIER on frequency.
-
- */
- #include <stdio.h>
- #include <dos.h>
- #include "global.h"
- #include "pc.h"
- #include "config.h"
- #include "mbuf.h"
- #include "ax25.h"
- #include "iface.h"
- #include "lapb.h"
- #include "proc.h"
- #include "trace.h"
- #include "netuser.h"
- #include "proc.h"
- #include "pktdrvr.h"
- #include "commands.h"
- #include "devparam.h"
- #include "gracilis.h"
- #include "p10.h"
-
- #ifdef OLD_KA9Q
- #else
- #define tprintf printf
- #endif
-
-
- #ifdef PACKETEN_DEBUG
- extern long recvcalls;
- extern long rawcalls;
- #endif
-
- extern UNI_DCB P10_udcb[];
-
-
- extern INTERRUPT (*P10oldvec) __ARGS((void)); /* Old vector contents */
- extern int16 P10_vec; /* Vector number */
-
- extern int16 P10Proc_id; /* The PC is processor 2!!! */
-
- extern IPC *P10Ipc;
- extern int16 P10Pcport;
-
- extern INTERRUPT (*P10handler) __ARGS((void));
-
-
- /********************************************************************
- * IPC_ATTACH *
- * *
- * File: ipc.c *
- * Rev : 1.0 *
- * *
- ********************************************************************
- *
- *
- * DESCRIPTION:
- * -----------
- * Attaches the PackeTen Switch's ipc driver to NOS.
- *
- * ARGUMENTS:
- * ---------
- * All argv's are strings
- * argv[0]: hardware type, "ipc"
- *
- * argv[1]: vector, e.g., "2"
- *
- * argv[2]: "0" = PACKETEN main card
- * "1" = PACKETEN daughter card
- * "2" = IBM PC side of IPC
- * argv[3]: interface "NAME"
- *
- * argv[4]: encap mode
- *
- * argv[5]: OPTIONAL - IPC memory base address
- *
- * argv[6]: OPTIONAL - PackeTen control Port address - Default 0x238
- *
- * argv[7]: OPTIONAL - Tx Queue Depth, num. of tx packets to allow in the
- * "to be transmitted queue" at one time.
- *
- * argv[8]: OPTIONAL - # of rx buffers to preallocate !!! NOT IMPLEMENTED
- *
- * argv[9]: OPTIONAL - Ip address
- *
- * RETURN VALUES:
- * -------------
- * 0 - success
- * -1 - failure, driver not attached and no memory left allocated
- *
- * GLOBAL INPUTS:
- * -------------
- *
- * GLOBAL OUTPUTS:
- * --------------
- *
- * FUNCTIONS CALLED:
- * ----------------
- * tprintf
- * calloc
- * malloc
- * free
- *
- * IO:
- * --
- *
- *
- ******************************************************************/
-
-
- int
- ipc_attach(argc,argv,p)
- int argc;
- char *argv[];
- void *p; /* new for NOS */
- {
- extern struct iface *ifaces;
- struct iface *intfc_p;
- IPC_DCB *sp;
- UNI_DCB *udcbp;
- int devnum, an_ipc_is_attached;
- int32 ipaddr; /* new for NOS */
- char i_state; /* saved state of the interrupt level */
- int i; /* gen purpose counter ... etc */
- struct ipcbuf *rxarea;
- long base_addr;
- int16 port;
-
- /*
- * validate input params
- */
- if ( argc < 5 )
- {
-
- tprintf("ipc_attach: too few arguments (%d) \r\n", argc);
- tprintf("ipc <vector> <processor (dc|mc)> <name> <mode> [base addr] [ctl addr]\r\n");
- tprintf(" [txQdepth] [rxbufs] [ip addr]\r\n");
- return(-1);
- }
-
-
- #ifdef PACKETEN_DEBUG
-
- tprintf("ipc_attach: argument count is %d\n",argc);
- for(i=0;i<argc;i++)
- tprintf("arg #%d: %s\n",i,argv[i]);
- tprintf("\n\n");
- #endif
-
- /* set the udcb device # for this processor's ipc */
- devnum = -1;
- if(strcmpi(argv[2],"mc") == 0) devnum = 0;
- if(strcmpi(argv[2],"dc") == 0) devnum = 1;
- if(strcmpi(argv[2],"pc") == 0) devnum = 2;
-
- if(devnum == -1)
- {
- tprintf("ipc_attach err: unknown processor id %s\r\n",argv[2]);
- tprintf("Try 'mc' for PackeTen Main Card or 'dc' for Daughter Card.\n");
- return(-1);
- }
-
- if((devnum) == P10Proc_id) /* Can't be same as Our local processor*/
- {
- tprintf("ipc_attach err: processor id %s is LOCAL!!!\r\n",argv[2]);
- tprintf("Try 'mc' for PackeTen Main Card or 'dc' for Daughter Card.\n");
- return(-1);
- }
-
-
- if ( if_lookup(argv[3]) != NULLIF ) /* new for NOS */
- {
- tprintf("Interface %s already exists \r\n", argv[3]);
- return(-1);
- }
-
- /* new for NOS, Set the IP address */
- ipaddr = Ip_addr; /* default value */
- if ( argc >= 10 )
- ipaddr = resolve(argv[9]);
- if ( ipaddr == 0 )
- {
- tprintf(Noipaddr);
- return(-1);
- }
-
- if(argc >= 6)
- {
- #ifdef PACKETEN_DEBUG
- tprintf("Base address = %lx\n",(unsigned long)ghtol(argv[5]));
- #endif
- P10Ipc = (IPC *)ghtol(argv[5]);
- base_addr = ptol(P10Ipc);
-
- if( (base_addr != 0x80000000) &&
- (base_addr != 0x90000000) &&
- (base_addr != 0xA0000000) &&
- (base_addr != 0xC0000000) &&
- (base_addr != 0xD0000000) &&
- (base_addr != 0xE0000000)
- )
- {
- tprintf("Bad IPC base address specified: %lx\n",base_addr);
- return(-1);
- }
-
-
- }
-
- /* Did the user specify a port address? */
- if(argc >= 7)
- {
- if((port = atoi(argv[6])) == 0)
- {
- tprintf("Illegal Control Port address specified: %s\n",argv[6]);
- return(-1);
- }
- else P10Pcport = port;
- }
-
- /* Gracilis 7/25/92 DGL */
- /* Be sure to enable the dual port RAM for release 2 CPU's */
- ipc_mapin(P10Pcport);
-
-
- udcbp = &P10_udcb[devnum]; /* dev num is index number!!! */
-
- /* See if already attached */
- if ( udcbp->attached )
- {
- tprintf("ipc_attach error: IPC channel already attached; interface is %s\n", argv[3]);
- return(-1);
- }
-
-
- /*
- * try to allocate necessary memory
- */
-
- intfc_p = (struct iface *)calloc(1,sizeof(struct iface));
- if ( intfc_p != (struct iface *)0 )
- {
- intfc_p->name = malloc((unsigned)strlen(argv[3])+2);
- if (intfc_p->name != NULLCHAR )
- {
- intfc_p->hwaddr = NULL;
- }
- else
- {
- free(intfc_p);
- tprintf("ipc_attach error: no memory for interface name, size 7 bytes, interface %s", argv[3]);
- return(-1);
- }
- }
- else
- {
- tprintf("ipc_attach error: no memory for interface struct, size of %d, interface %s", sizeof(struct iface),argv[3]);
- return(-1);
- }
-
- /* allocate and clear the device control block */
- sp = (IPC_DCB *)calloc(1,sizeof(IPC_DCB));
- if ( sp == (IPC_DCB *)0 )
- {
- free(intfc_p->name);
- free(intfc_p);
- tprintf("ipc_attach error: no memory for device control block structure, size of %d, interface %s", sizeof(IPC_DCB),argv[3]);
- return(-1);
- }
-
-
- /* this needs to be done BEFORE the buffers are allocated... */
- /* DGL 4/17/90 */
-
- /* 7/25/92 DGL */
- /* intfc_p->type = CL_AX25; */
- /* attempt to set the encapsulation type */
- /* This needs to be done before we preallocate */
- /* receive buffers, since we have to indicate the */
- /* encap type in the buffers for later use. */
- /* Only allow type "IPC" or "AX25" */
- if(((strcmpi(argv[4],"ax25") != 0) &&
- (strcmpi(argv[4],"ipc") != 0)) ||
- (setencap(intfc_p,argv[4]) != 0))
- {
- /* An invalid encap mode was specified... */
- /* Just print a message and exit */
- tprintf("Illegal mode specification: %s\n",argv[4]);
- free(intfc_p->name);
- free(intfc_p);
- free(sp);
- return(-1);
- }
-
- /* preallocate rx buffers */
- /* set the rxavailbufs parameter */
- if ( argc >= 9 )
- sp->rxavailbufs = atoi(argv[8]);
- else
- sp->rxavailbufs = IPC_BUF_CNT + 1;
-
- /* get the requested rx pre-allocated mbuf's */
- sp->rxavailq = NULLBUF;
-
-
- f_getavail(&(sp->rxavailq), (sp->rxavailbufs), IPC_BUF_SIZE, &(sp->rxavailcount), intfc_p, (bool)FALSE);
-
- #ifdef PACKETEN_DEBUG
- tprintf("ipc_attach: rxavailbufs is %d, rxavailcount is %d\n", sp->rxavailbufs, sp->rxavailcount);
- #endif
-
- if(sp->rxavailcount < sp->rxavailbufs)
- {
- tprintf("ipc_attach: Insufficient Memory to preallocate rx buffers...\n");
- free(intfc_p->name);
- free(intfc_p);
-
- /* Now free all successfully allocated buffers... */
- while((sp->rxbufp = f_dequeavail(&sp->rxavailq,&sp->rxavailcount)) != NULLBUF)
- free(sp->rxbufp);
-
- free(sp);
- return(-1);
- }
-
- /* setup the receive buffer pointer */
- sp->rxbufp = f_dequeavail(&sp->rxavailq,&sp->rxavailcount);
-
- /*
- * Setup the interface structure and link it to the list
- * of interface structures.
- */
- /* the Ascii name of the driver unit */
- strcpy(intfc_p->name,argv[3]);
-
- /* fill in this "Unit's" driver control block */
-
- intfc_p->mtu = (IPC_BUF_SIZE - MAX_AX25_HDR_LEN);
- intfc_p->ioctl = ipc_ioctl;
- intfc_p->raw = ipc_raw;
- intfc_p->stop = ipc_stop;
- intfc_p->dev = devnum;
- intfc_p->addr = ipaddr;
-
- /* new for NOS Mycall replaces (char *)&mycall */
- intfc_p->hwaddr = mallocw(AXALEN);
- memcpy(intfc_p->hwaddr,Mycall,AXALEN);
-
-
- /* lastly, but very importantly, put in the LL of interfaces */
- intfc_p->next = Ifaces;
- Ifaces = intfc_p;
-
-
- /*
- * Initialize the unit's driver control block
- */
- sp->iface = intfc_p; /* new for NOS - save the iface */
- /* address for use in queueing */
- /* mbufs onto Hopper */
- sp->destproc = (devnum);
- sp->xmtq = (struct drvbuf *)0;
- sp->xmtqtail = (struct drvbuf *)0;
- sp->freem = (struct drvbuf *)0;
-
- if ( argc >= 8 )
- sp->txq_depth = atoi(argv[7]);
- else
- sp->txq_depth = IPC_TX_DEPTH_DEFAULT;
-
-
- /* no need to init stats because calloc zero-ed the sp */
- sp->intcnt = 0;
- sp->txcnt = 0;
-
- /*
- * Now for the hardware dependent initializations.
- *
- * intfc_p->dev tells which unit/dev
- *
- */
- #ifdef PACKETEN_DEBUG
- tprintf("ipc_attach: intfc_p->dev = %x config IPC HW \r\n", intfc_p->dev);
- #endif
-
-
-
- /* HERE WE start DIDDLING the actual hardware regs... */
- /* So to be safe, NO ints... */
- i_state = dirps();
-
- /* reset all possible pending ints for IPC */
- clrint302dc();
- clrint302mc();
-
- switch(P10Proc_id)
- {
- case 0: switch(sp->destproc)
- {
- case 1: sp->rxarea = (struct ipcbuf *)P10Ipc->proc[0].proc_buf[0];
- sp->rxcontrol = (uchar *)&P10Ipc->proc[0].control[0];
- sp->txcontrol = (uchar *)&P10Ipc->proc[1].control[0];
- sp->txarea = (struct ipcbuf *)P10Ipc->proc[1].proc_buf[0];
- break;
-
- case 2: sp->rxarea = (struct ipcbuf *)P10Ipc->proc[0].proc_buf[1];
- sp->rxcontrol = (uchar *)&P10Ipc->proc[0].control[1];
- sp->txcontrol = (uchar *)&P10Ipc->proc[2].control[0];
- sp->txarea = (struct ipcbuf *)P10Ipc->proc[2].proc_buf[0];
- break;
-
- default: break;
- }
- break;
-
- case 1: switch(sp->destproc)
- {
- case 0: sp->rxarea = (struct ipcbuf *)P10Ipc->proc[1].proc_buf[0];
- sp->rxcontrol = (uchar *)&P10Ipc->proc[1].control[0];
- sp->txcontrol = (uchar *)&P10Ipc->proc[0].control[0];
- sp->txarea = (struct ipcbuf *)P10Ipc->proc[0].proc_buf[0];
- break;
-
- case 2: sp->rxarea = (struct ipcbuf *)P10Ipc->proc[1].proc_buf[1];
- sp->rxcontrol = (uchar *)&P10Ipc->proc[1].control[1];
- sp->txcontrol = (uchar *)&P10Ipc->proc[2].control[1];
- sp->txarea = (struct ipcbuf *)P10Ipc->proc[2].proc_buf[1];
- break;
-
- default: break;
- }
- break;
-
- case 2: switch(sp->destproc)
- {
- case 0: sp->rxarea = (struct ipcbuf *)P10Ipc->proc[2].proc_buf[0];
- sp->rxcontrol = (uchar *)&P10Ipc->proc[2].control[0];
- sp->txcontrol = (uchar *)&P10Ipc->proc[0].control[1];
- sp->txarea = (struct ipcbuf *)P10Ipc->proc[0].proc_buf[1];
- break;
-
- case 1: sp->rxarea = (struct ipcbuf *)P10Ipc->proc[2].proc_buf[1];
- sp->rxcontrol = (uchar *)&P10Ipc->proc[2].control[1];
- sp->txcontrol = (uchar *)&P10Ipc->proc[1].control[1];
- sp->txarea = (struct ipcbuf *)P10Ipc->proc[1].proc_buf[1];
- break;
-
- default: break;
- }
- break;
-
-
- default : tprintf("Invalid processor ID!!!\n");
- break;
- }
-
-
-
- /* Initialize IPC RX buffer descriptors */
-
- rxarea = sp->rxarea;
-
- #ifdef PACKETEN_DEBUG
- restore(i_state);
- tprintf("rxarea's at:\n");
- #endif
- for(i=0;i<IPC_BUF_CNT;i++)
- {
- #ifdef PACKETEN_DEBUG
- tprintf("%d at %lx; ",i, &rxarea[i]);
- #endif
- /* mark the buffers inactive */
- rxarea[i].active = (unsigned char)FALSE;
- rxarea[i].msbcnt = (unsigned char)0;
- rxarea[i].lsbcnt = (unsigned char)0;
- }
- #ifdef PACKETEN_DEBUG
- tprintf("\n");
- fflush(stdout);
- i_state = dirps();
- #endif
- an_ipc_is_attached = FALSE;
- /* 0,1,2 are IPC chan/dev */
- for (i=0; i<P10_MAXIPC; i++)
- if (P10_udcb[i].type == IPC_LINK) an_ipc_is_attached = TRUE;
-
-
- /* only set the vector if no IPC link is attached */
- if ( an_ipc_is_attached == FALSE )
- {
- /* tell other processors this processor is talking */
- P10Ipc->active[P10Proc_id] = TRUE;
-
- /* Save old vector and write new vector */
- P10_vec = htoi(argv[1]);
- P10oldvec = getirq(P10_vec);
-
- /* Write ipc's interrupt vector */
- if (setirq(P10_vec, P10handler) == -1)
- {
- tprintf("ipc_attach err:IRQ %u out of range\n",P10_vec);
- free(intfc_p->name);
- free(intfc_p);
- /* Now free all successfully allocated buffers... */
- while ( (sp->rxbufp = f_dequeavail(&sp->rxavailq,&sp->rxavailcount)) != NULLBUF)
- free(sp->rxbufp);
-
- free(sp);
- restore(i_state);
- return(-1);
- }
- }
-
- /* send control msg to other end, tell him I reset my ipc link */
-
- #ifdef PACKETEN_DEBUG
- restore(i_state);
- tprintf("sp->txcontrol = %lx\n",sp->txcontrol);
- fflush(stdout);
- i_state = dirps();
- #endif
- *sp->txcontrol = IPC_RESET;
- sp->txindex = sp->rxindex = 0;
- *sp->rxcontrol = 0;
-
- /* force an interrupt to destination processor, to make him see */
- /* my control message */
-
- /* If the destination is the "Main Card"... */
-
- if(sp->destproc == 0)
- int302mc();
- else /* otherwise interrupt daughter 302 card */
- int302dc();
-
- /*
- * Universal Driver Control Block and
- * Vector related initializations
- */
- udcbp->attached = TRUE;
- udcbp->type = IPC_LINK;
-
- /* set address of the unit's driver control block */
- udcbp->dcbp = (char *)sp;
-
- /* enable general ints */
- restore(i_state);
-
- /* new for NOS - start the two processes needed by the */
- /* sync driver; one is for getting pre-allocated buffers */
- /* the other is for kicking the transmitter after its */
- /* timer has expired or when it needs a transmitted */
- /* message free-ed. P.S. must do after attached set to TRUE */
- #ifdef PACKETEN_DEBUG
- tprintf("ipc_attach: calling newproc for ipc_rxavget \n");
- #endif
- sp->rxavproc = newproc("ipc rxavget",150,ipc_rxavget,devnum,NULL,NULL,0);
-
- #ifdef PACKETEN_DEBUG
- tprintf("ipc_attach: calling newproc for ipc_freetx \n");
- #endif
- sp->freetxproc = newproc("ipc freetx",150,ipc_freetx,devnum,NULL,NULL,0);
-
-
- /* DONE */
- #ifdef PACKETEN_DEBUG
- tprintf("ipc_attach: All done!!! \n");
- #endif
-
- if ( an_ipc_is_attached == FALSE )
- maskon(P10_vec);
-
- return(0);
- }
- /*
- * End of ipc_attach()
- ******************************************************************/
-
- /*
- * Display a PackeTen Switch Inter-Processor Communications channel's
- * statistics.
- */
- int
- doipcstat(argc,argv,p)
- int argc;
- char *argv[];
- void *p; /* new for NOS */
- {
- IPC_DCB *dcbp;
- UNI_DCB *udcbp;
- int16 dev;
-
- /* Header for the IPC channel's on the card */
- tprintf("\n PackeTen Switch Inter-Processor Comm Channel Statistics\n\n");
- tprintf("Name/To RxPacks RxNoBufs TxPacks TxFlush IntCnt TxqDepth RxAvail\n");
- tprintf("------- --------- -------- --------- -------- --------- -------- -------\n");
-
- for (dev=0, udcbp = &P10_udcb[0]; dev < P10_MAXIPC; udcbp++, dev++)
- {
- if ( udcbp->type == IPC_LINK )
- {
- dcbp = (IPC_DCB *)udcbp->dcbp;
-
- /* tprintf("%4s/%2s %9.9d %8.8ld %9.9ld %8.8ld %9.9ld %8.8ld %7.7ld\n",
- */
- tprintf("%4s/%2s %#9lu %#8u %#9lu %#8u %#9lu %#8u %#7u\n",
-
- dcbp->iface->name,
- ((dev == 5)?"MC": (dev == 6)?"DC" : "PC"),
- dcbp->rxpackcnt,
- dcbp->nobufs,
- dcbp->txpackcnt,
- dcbp->txflush,
- dcbp->intcnt,
- dcbp->txq_depth,
- dcbp->rxavailcount);
- }
-
- } /* end of for loop */
-
- tprintf("\n");
- return(0);
- }
-
-
- /* Subroutine to set kiss params in channel tables */
- int32
- ipc_ioctl(iface,cmd,set,val)
- struct iface *iface;
- int cmd;
- int set;
- int32 val;
- {
- IPC_DCB *dcbp;
-
- dcbp = (IPC_DCB *)P10_udcb[iface->dev].dcbp;
-
- switch(cmd){
- case PARAM_RXBUFS:
- if(set)
- {
- dcbp->rxavailbufs = (int16)val;
-
- /* signal the process which */
- /* allocates the rx buffers */
- psignal(&ipc_bufpp[dcbp->destproc],1);
- }
-
- return dcbp->rxavailbufs;
-
- case PARAM_TXQMAX:
- if(set)
- dcbp->txq_depth = (int16)val;
- return dcbp->txq_depth;
-
- }
- return -1;
- }
-
- /*
- * Stop I/O
- */
- int
- ipc_stop(intfcp)
- struct iface *intfcp;
- {
- IPC_DCB *sp;
- int16 dev;
- UNI_DCB *udcbp;
- int16 i_state, i, an_ipc_is_attached;
- struct drvbuf *xbufp, *tmpptr;
- struct mbuf *tmpmbufp;
-
- dev = intfcp->dev;
- udcbp = &P10_udcb[dev]; /* dev num is index number!!! */
-
- if ( udcbp->attached != TRUE )
- {
- tprintf("ipc_stop err: Device already stopped/de-attached!!\n");
- return(0);
- }
-
- sp = (IPC_DCB *)P10_udcb[dev].dcbp;
-
- /* Turn off interrupts */
- i_state = dirps();
-
- /* mark ipc as available - do it now for if below */
- udcbp->attached = FALSE;
- udcbp->type = 0;
- udcbp->dcbp = NULL;
-
-
- an_ipc_is_attached = FALSE;
- for (i=0; i<P10_MAXIPC; i++)
- if (P10_udcb[i].type == IPC_LINK)
- an_ipc_is_attached = TRUE;
-
- /* when both IPC interfaces are stopped - tell other */
- /* processors' this processor ain't talking */
- if ( an_ipc_is_attached == FALSE )
- {
- /* tell the other processors this processor's IPC */
- /* is closed */
- P10Ipc->active[P10Proc_id] = FALSE;
-
- /* Turn off interrupts */
- maskoff(P10_vec);
-
- /* Restore interrupt vector used by IPC handler */
- setirq(P10_vec, P10oldvec);
- }
-
- restore(i_state);
-
- /* kill off the support processes */
- /* so they don't allocate memory */
- /* whils't we're freeing it */
-
- killproc(sp->rxavproc);
- killproc(sp->freetxproc);
-
-
- /*
- * Flush all buffers and queue's
- */
-
-
- /* free preallocated rx buffers on the rx available queue */
-
- while((tmpmbufp = f_dequeavail(&sp->rxavailq,&sp->rxavailcount)) != NULLBUF)
- free(tmpmbufp);
-
- /* free up any pending transmit buffers... */
- while(sp->xmtq != (struct drvbuf *)0 )
- {
- tmpptr = sp->xmtq->next;
- free(sp->xmtq);
- sp->xmtq = tmpptr;
- }
-
- /* Free any previously sent frames, which are in the waiting to be */
- /* free'd queue */
-
- /* disable ints here to get queue head... */
- i_state = dirps(); /* seems unecessary */
- xbufp = sp->freem;
- sp->freem = (struct drvbuf *)0;
- restore(i_state);
-
- /* Here xbufp is a "to be free'd" */
- /* queue pointer" */
- /* now free memory of all the xmitted messages */
- while ( xbufp != (struct drvbuf *)0 )
- {
- tmpptr = xbufp->next;
- free((char *)xbufp);
- xbufp = tmpptr;
- }
-
-
- /*
- * Deallocate other driver related memory structures
- */
- if ( sp->rxbufp != NULLBUF )
- free(sp->rxbufp);
- free(sp);
-
- return(0);
- }
-
- /* Convert hex-ascii to integer */
- static long int
- ghtol(s)
- char *s;
- {
- long int i = 0;
- char c;
-
- while((c = *s++) != '\0'){
- if(c == 'x')
- continue; /* allow 0x notation */
- if(c == ':')
- continue; /* allow : for seg:offset notation */
- if('0' <= c && c <= '9')
- i = (i * 16) + (c - '0');
- else if('a' <= c && c <= 'f')
- i = (i * 16) + (c - 'a' + 10);
- else if('A' <= c && c <= 'F')
- i = (i * 16) + (c - 'A' + 10);
- else
- break;
- }
- return i;
- }
-
-